package cn.llyong.rpc.common.registry;

import cn.llyong.rpc.common.config.MonkeyRpcProperties;
import cn.llyong.rpc.common.constant.Constants;
import cn.llyong.rpc.common.exception.RpcException;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;

/**
 * @description: 服务注册
 * @author: lvyong
 * @date: 2020年06月24日 08:46
 */
public class ServiceRegistry {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MonkeyRpcProperties rpcProperties;

    public static CuratorFramework zkClient = null;

    @PostConstruct
    public void init(){
        connect(rpcProperties.getRegistryAddr());
    }

    private  boolean connect(String registryAddr){
        zkClient = CuratorFrameworkFactory.builder()
                .connectString(registryAddr)
                .sessionTimeoutMs(30*60*1000)
                .retryPolicy(new RetryNTimes(3, 3000))
//                .namespace("")
                .build();
        zkClient.start();
        logger.info("连接上zookeeper！！！");
        return zkClient != null;
    }

    /**
     * 服务注册
     * @param nodePath  节点路径
     * @param nodeData  节点数据
     * @return
     */
    public String register(String nodePath, String nodeData) throws RpcException {
        isConnected();

        String path = null;
        try {
            String serverPath = Constants.ROOT_PATH + nodePath;
            //递归创建，最后的节点类型为临时节点
            path =  zkClient.create().creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL)
                    .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                    .forPath(serverPath, nodeData.getBytes("UTF-8"));
            logger.info("服务注册成功，节点路径: {} ", path);
        }catch (KeeperException.NodeExistsException e){
            logger.error("服务注册失败，该服务器节点 {} 已经注册,请修改！！！",e.getPath());
            throw new RpcException("服务注册失败，该服务器节点 "+ e.getPath() +" 已经注册,请修改！！！");
        } catch (Exception e) {
            throw new RpcException(e);
        }
        return path;
    }

    /**
     * 判断是否建立连接
     */
    private void isConnected(){
        if (zkClient == null){
            throw new RpcException("have not connect Zookeeper Server");
        }
    }
}
